﻿using System;
using System.IO;
using System.Net;
using System.Text;

namespace JustinAngel.Neurons.Framework
{
    public class WebRequestMaker : IWebRequestMaker
    {
        [Dependency]
        public INetworkStatusProvider NetworkStatusProvider { get; set; }


        public void StartWithCredentialsAndTimeout(string requestUri, TimeSpan timeout, Action<Stream> onCompleted, Action OnTimeoutOrTechFail)
        {
            if (!NetworkStatusProvider.IsConnected)
            {
                OnTimeoutOrTechFail();
                return;
            }

            var requestState = new RequestState();


            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(requestUri);

            request.Method = "GET";
            var async = request.BeginGetResponse(result =>
            {
                if (!request.HaveResponse)
                {
                    if (!requestState.WasFailureOrCompleteInvoked)
                        OnTimeoutOrTechFail();
                    requestState.WasFailureInvoked = true;
                }
                else
                {
                    try
                    {
                        var response = request.EndGetResponse(result);

                        var responseStream = response.GetResponseStream();
                        if (responseStream.CanRead)
                        {
                            if (!requestState.WasFailureOrCompleteInvoked)
                                onCompleted(responseStream);
                            requestState.WasCompletedInvoked = true;
                        }
                        else
                        {
                            if (!requestState.WasFailureOrCompleteInvoked)
                                OnTimeoutOrTechFail();
                            requestState.WasFailureInvoked = true;
                        }
                    }
                    catch (Exception ex)
                    {
                        if (!requestState.WasFailureOrCompleteInvoked)
                            OnTimeoutOrTechFail();
                        requestState.WasFailureInvoked = true;
                    }
                }
            }, null);

            DispatcherTimerHelper.On(timeout, () =>
            {
                if (!request.HaveResponse && !requestState.WasFailureOrCompleteInvoked)
                {
                    request.Abort();
                    requestState.WasFailureInvoked = true;
                    OnTimeoutOrTechFail();
                }
            });
        }

        public void Start2(string URL, Action<Stream, Exception, object> End, object state)
        {
            if (NetworkStatusProvider.IsConnected)
            {
                HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL);
                request.BeginGetResponse((result) =>
                {
                    WebResponse response = null;
                    try
                    {
                        response = request.EndGetResponse(result);
                    }
                    catch (Exception ex)
                    {
                        End(null, ex, result.AsyncState);
                        return;
                    }
                    End(response.GetResponseStream(), null, result.AsyncState);
                }, state);
            }
            else
            {
                End(null, null, state);
            }
        }
    }

    public class RequestState
    {
        public bool WasFailureOrCompleteInvoked
        {
            get { return WasCompletedInvoked || WasFailureInvoked; }
        }
        public bool WasFailureInvoked { get; set; }
        public bool WasCompletedInvoked { get; set; }
    }
}
